#include "tool_Fifo.h"
#include "sys_Debug.h"

/**
 * @brief   获取缓冲区已占用长度
 * @param   None
 * @return  缓冲区已占用长度
 */
int tool_Fifo::getCount()
{
    if (tail >= head)
        return tail - head;
    else
        return tail + buffer_length - head;
}

/**
 * @brief   将数据压入队列
 * @param   pData   数据
 * @return  QUEUE_ret---QUEUE_OK = 0x00U,
                        QUEUE_ERROR = 0x01U,
                        QUEUE_BUSY = 0x02U,
                        QUEUE_TIMEOUT = 0x03U,
                        QUEUE_OVERLOAD = 0x04U,
                        QUEUE_VOID = 0x05U
 */
tool_Fifo::QUEUE_ret tool_Fifo::push(QUEUE_DATA_T pData)
{
    unsigned int index = (tail + 1) % buffer_length;
    if (index == head)
    {
        SysError("QUEUE_OVERLOAD\r\n");
        return QUEUE_OVERLOAD;
    }
    else
    {
        buffer[tail] = pData;
        tail = index;
        return QUEUE_OK;
    }
}

/**
 * @brief   将数据从队列中取出
 * @param   pData   数据地址指针
 * @return  QUEUE_ret---QUEUE_OK = 0x00U,
                        QUEUE_ERROR = 0x01U,
                        QUEUE_BUSY = 0x02U,
                        QUEUE_TIMEOUT = 0x03U,
                        QUEUE_OVERLOAD = 0x04U,
                        QUEUE_VOID = 0x05U
 */
tool_Fifo::QUEUE_ret tool_Fifo::pop(QUEUE_DATA_T *pData)
{
    if (head == tail)
    {
        SysError("QUEUE_VOID\r\n");
        return QUEUE_VOID;
    }
    else
    {
        *pData = buffer[head];
        head = (head + 1) % buffer_length;
        return QUEUE_OK;
    }
}

/**
 * @brief   将指定长度数据压入队列
 * @param   pData   数据地址指针
 * @param   size    数据长度
 * @return  QUEUE_ret---QUEUE_OK = 0x00U,
                        QUEUE_ERROR = 0x01U,
                        QUEUE_BUSY = 0x02U,
                        QUEUE_TIMEOUT = 0x03U,
                        QUEUE_OVERLOAD = 0x04U,
                        QUEUE_VOID = 0x05U
 */
tool_Fifo::QUEUE_ret tool_Fifo::pushArray(QUEUE_DATA_T *pData, int size)
{
    int i = 0;
    if ((buffer_length - getCount()) <= size)
    {
        SysError("QUEUE_INSUFFICIENT\r\n");
        return QUEUE_INSUFFICIENT;
    }
    else
        for (i = 0; i < size; i++)
        {
            if (push(*pData) == QUEUE_OK)
            {
                pData++;
            }
            else
            {
                return QUEUE_OVERLOAD;
            }
        }
    return QUEUE_OK;
}

/**
 * @brief   将指定长度数据从队列中取出
 * @param   pData   数据地址指针
 * @param   size    数据长度
 * @return  QUEUE_ret---QUEUE_OK = 0x00U,
                        QUEUE_ERROR = 0x01U,
                        QUEUE_BUSY = 0x02U,
                        QUEUE_TIMEOUT = 0x03U,
                        QUEUE_OVERLOAD = 0x04U,
                        QUEUE_VOID = 0x05U
 */
tool_Fifo::QUEUE_ret tool_Fifo::popArray(QUEUE_DATA_T *pData, int size)
{
    int i = 0;
    if (getCount() < size)
    {
        SysError("QUEUE_MISS\r\n");
        return QUEUE_MISS;
    }
    else
        for (i = 0; i < size; i++)
        {
            if (pop(pData) == QUEUE_OK)
            {
                pData++;
            }
            else
            {
                return QUEUE_VOID;
            }
        }
    return QUEUE_OK;
}

void tool_Fifo::clear()
{
    head = 0;
    tail = 0;
}

#if DEMO_FIFO
QUEUE_DATA_T demoBuffer[256] = {0};
tool_Fifo demoFifo(demoBuffer, 256);
#endif
